/***************************************************************************
 *   Copyright (c) 2010 Thomas Anderson <ta@nextgenengineering>            *
 *                                                                         *
 *   This file is part of the FreeCAD CAx development system.              *
 *                                                                         *
 *   This library is free software; you can redistribute it and/or         *
 *   modify it under the terms of the GNU Library General Public           *
 *   License as published by the Free Software Foundation; either          *
 *   version 2 of the License, or (at your option) any later version.      *
 *                                                                         *
 *   This library  is distributed in the hope that it will be useful,      *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU Library General Public License for more details.                  *
 *                                                                         *
 *   You should have received a copy of the GNU Library General Public     *
 *   License along with this library; see the file COPYING.LIB. If not,    *
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
 *   Suite 330, Boston, MA  02111-1307, USA                                *
 *                                                                         *
 ***************************************************************************/

#include "pch.h"

#include <sstream>

#include <QtWidgets/QMainWindow>

#include "Gui/Application.h"
#include "GuiApplicationNativeEventAware.h"
#include "SpaceballEvent.h"


#if defined(_USE_3DCONNEXION_SDK) || defined(SPNAV_FOUND)
#if defined(Q_OS_LINUX)
  #if defined(SPNAV_USE_X11)
    #include "3Dconnexion/GuiNativeEventLinuxX11.h"
  #else
    #include "3Dconnexion/GuiNativeEventLinux.h"
  #endif
#elif defined(Q_OS_WIN)
  #include "3Dconnexion/GuiNativeEventWin32.h"
#elif defined(Q_OS_MACX)
  #include "3Dconnexion/GuiNativeEventMac.h"
#endif // Platform switch
#endif // Spacemice

Gui::GUIApplicationNativeEventAware::GUIApplicationNativeEventAware(int &argc, char *argv[]) :
        QApplication (argc, argv), spaceballPresent(false)
{
#if defined(_USE_3DCONNEXION_SDK) || defined(SPNAV_FOUND)
    nativeEvent = new Gui::GuiNativeEvent(this);
#endif
}

Gui::GUIApplicationNativeEventAware::~GUIApplicationNativeEventAware()
{
}

void Gui::GUIApplicationNativeEventAware::initSpaceball(QMainWindow *window)
{
#if defined(_USE_3DCONNEXION_SDK) || defined(SPNAV_FOUND)
    nativeEvent->initSpaceball(window);
#else
    Q_UNUSED(window);
#endif
    Spaceball::MotionEvent::MotionEventType = QEvent::registerEventType();
    Spaceball::ButtonEvent::ButtonEventType = QEvent::registerEventType();
}

bool Gui::GUIApplicationNativeEventAware::processSpaceballEvent(QObject *object, QEvent *event)
{
    if (!activeWindow()) {
        qDebug("No active window\n");
        return true;
    }

    QApplication::notify(object, event);
    if (event->type() == Spaceball::MotionEvent::MotionEventType)
    {
        Spaceball::MotionEvent *motionEvent = dynamic_cast<Spaceball::MotionEvent*>(event);
        if (!motionEvent)
            return true;
        if (!motionEvent->isHandled())
        {
            //make a new event and post to parent.
            Spaceball::MotionEvent *newEvent = new Spaceball::MotionEvent(*motionEvent);
            postEvent(object->parent(), newEvent);
        }
    }

    if (event->type() == Spaceball::ButtonEvent::ButtonEventType)
    {
        Spaceball::ButtonEvent *buttonEvent = dynamic_cast<Spaceball::ButtonEvent*>(event);
        if (!buttonEvent)
            return true;
        if (!buttonEvent->isHandled())
        {
            //make a new event and post to parent.
            Spaceball::ButtonEvent *newEvent = new Spaceball::ButtonEvent(*buttonEvent);
            postEvent(object->parent(), newEvent);
        }
    }
    return true;
}

void Gui::GUIApplicationNativeEventAware::postMotionEvent(std::vector<int> motionDataArray)
{
	auto currentWidget(focusWidget());
    if (!currentWidget) {
        return;
    }
    importSettings(motionDataArray);

	Spaceball::MotionEvent *motionEvent = new Spaceball::MotionEvent();
    motionEvent->setTranslations(motionDataArray[0], motionDataArray[1], motionDataArray[2]);
    motionEvent->setRotations(motionDataArray[3], motionDataArray[4], motionDataArray[5]);
    this->postEvent(currentWidget, motionEvent);
}

void Gui::GUIApplicationNativeEventAware::postButtonEvent(int buttonNumber, int buttonPress)
{
	auto currentWidget(focusWidget());
    if (!currentWidget) {
        return;
    }

    Spaceball::ButtonEvent *buttonEvent = new Spaceball::ButtonEvent();
    buttonEvent->setButtonNumber(buttonNumber);
    if (buttonPress)
    {
	  buttonEvent->setButtonStatus(Spaceball::BUTTON_PRESSED);
    }
    else
    {
	  buttonEvent->setButtonStatus(Spaceball::BUTTON_RELEASED);
    }
    this->postEvent(currentWidget, buttonEvent);
}

float Gui::GUIApplicationNativeEventAware::convertPrefToSensitivity(int value)
{
    if (value < 0)
    {
        return ((0.9/50)*float(value) + 1);
    }
    else
    {
        return ((2.5/50)*float(value) + 1);
    }
}

void Gui::GUIApplicationNativeEventAware::importSettings(std::vector<int>& motionDataArray){}

// #include "moc_GuiApplicationNativeEventAware.cpp"
